package com.colors.diners.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.colors.commons.constant.ApiConstant;
import com.colors.commons.exception.ParameterException;
import com.colors.commons.model.domain.ResultInfo;
import com.colors.commons.model.dto.DinersDTO;
import com.colors.commons.model.pojo.Diners;
import com.colors.commons.model.vo.ShortDinerInfo;
import com.colors.commons.model.vo.SignInDinerInfo;
import com.colors.commons.utils.AssertUtil;
import com.colors.commons.utils.ResultInfoUtil;
import com.colors.diners.config.OAuth2ClientConfiguration;
import com.colors.diners.domain.OAuthDinerInfo;
import com.colors.diners.mapper.DinersMapper;
import com.colors.diners.vo.LoginDinerInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.connection.BitFieldSubCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author colors
 * @date 2021/4/29 16:13
 */
@Service
public class DinersService {

    @Resource
    private RestTemplate restTemplate;
    @Resource
    private RedisTemplate redisTemplate;

    @Value("${service.name.server-oauth2}")
    private String oauth2ServerName;

    @Resource
    private OAuth2ClientConfiguration oAuth2ClientConfiguration;

    @Resource
    private DinersMapper dinersMapper;
    @Resource
    private SendVerifyCodeService sendVerifyCodeService;



    /**
     * 根据主键查询食客信息
     *
     * @param ids
     * @return
     */
    public List<ShortDinerInfo> findByIds(String ids) {
        AssertUtil.isNotEmpty(ids, "请选择需要查询的人");
        String[] idArr = ids.split(",");
        List<ShortDinerInfo> diners = dinersMapper.findByIds(idArr);
        return diners;
    }


    /**
     * 注册
     *
     * @param dinersDTO
     * @param path
     * @return
     */
    public ResultInfo register(DinersDTO dinersDTO, String path) {
        // 检验参数
        String username = dinersDTO.getUsername();
        AssertUtil.isNotEmpty(username, "请输入用户名");
        String password = dinersDTO.getPassword();
        AssertUtil.isNotEmpty(password, "请输入密码");
        String phone = dinersDTO.getPhone();
        AssertUtil.isNotEmpty(phone, "手机号不能为空");
        String verifyCode = dinersDTO.getVerifyCode();
        AssertUtil.isNotEmpty(verifyCode, "验证码不能为空");
        // 检查验证码一致性
        String code = sendVerifyCodeService.getVerifyCode(phone);
        AssertUtil.isNotEmpty(code, "验证码已过期,请重新获取");
        AssertUtil.isTrue(!verifyCode.equals(code), "验证码不一致，请重新输入");
        // 检验用户已经注册
        Diners diners = dinersMapper.selectByUsername(username.trim());
        AssertUtil.isTrue(diners != null, "该用户已注册");
        // 注册
        dinersDTO.setPassword(DigestUtil.md5Hex(password));
        dinersMapper.save(dinersDTO);
        // 自动登录
        ResultInfo resultInfo = signIn(username.trim(), password.trim(), path);
        return resultInfo;
    }

    public void checkPhoneIsRegistered(String phone) {
        AssertUtil.isNotEmpty(phone, "手机号不能为空");
        Diners diners = dinersMapper.selectByPhone(phone);
        AssertUtil.isNotNull(diners, "该手机号未注册");
        AssertUtil.isTrue(diners.getIsValid() == 0, "该用户已锁定，请联系管理员！");
    }

    /**
     * 登录
     *
     * @param account
     * @param password
     * @param path
     * @return
     */
    public ResultInfo signIn(String account, String password, String path) {
        // 参数检验
        AssertUtil.isNotEmpty(account, "请输入账号");
        AssertUtil.isNotEmpty(password, "请输入密码");
        // 构建请求头
        HttpHeaders headers = new HttpHeaders();
        // 请求头为 表单
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        // 构建请求体
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("username", account);
        body.add("password", password);
        // 添加grant_type 和 score
        body.setAll(BeanUtil.beanToMap(oAuth2ClientConfiguration));
        // 把 请求头 和 请求体 封装成http entity
        HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(body, headers);

        // 设置authorization
        restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(oAuth2ClientConfiguration.getClientId(),
                oAuth2ClientConfiguration.getSecret()));

        // 发送请求
        ResponseEntity<ResultInfo> result = restTemplate.postForEntity(oauth2ServerName + "oauth/token", entity, ResultInfo.class);

        // 返回处理结果
        AssertUtil.isTrue(result.getStatusCode() != HttpStatus.OK, "登录失败");
        ResultInfo resultInfo = result.getBody();
        if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) {
            // 登录失败
            resultInfo.setData(resultInfo.getMessage());
            return resultInfo;
        }

        // 这里的 Data 是一个 LinkedHashMap 转成了域对象 OAuthDinerInfo
        OAuthDinerInfo dinerInfo = BeanUtil.fillBeanWithMap((LinkedHashMap) resultInfo.getData(),
                new OAuthDinerInfo(), false);
        // 根据业务需求返回视图对象
        LoginDinerInfo loginDinerInfo = new LoginDinerInfo();
        loginDinerInfo.setNickname(dinerInfo.getNickname());
        loginDinerInfo.setAvatarUrl(dinerInfo.getAvatarUrl());
        loginDinerInfo.setToken(dinerInfo.getAccessToken());

        return ResultInfoUtil.buildSuccess(path, loginDinerInfo);

    }

}
